package com.jdj.framework.dao.mybatis.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.jdj.framework.dao.mybatis.utils.EntityUtil;
import java.beans.Transient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * 实体的抽象父类,支持spring mvc 框架的反序列化,忽略页面端提交了实体 没有的字段
 *
 * @author caijinbang
 * @date 2019-04-14 11:48
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class BaseEntity implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -6437253381906993752L;

    /**
     * 主键字段名默认id
     */
    public static final String DEFAULT_FIELD_NAME_PRIMARY_KEY = "id";

    /**
     * 实体主键
     */
    protected String id;

    /**
     * 创建时间
     */
    protected Date createTime;

    /**
     * 创建人
     */
    protected Long createUserId;

    /**
     * 更新时间
     */
    protected Date updateTime;

    /**
     * 更新人
     */
    protected Long updateUserId;


    /**
     * 设值的字段
     */
    private List<String> settedFields = new ArrayList<String>();

    /**
     * 指定 设值实体字段 集合 已经标识设置过值的字段将被清空 设置传人的字段名数组
     *
     * @param fieldNameArr
     */
    public void setupSettedFieldArr(String[] fieldNameArr) {
        settedFields.clear();
        settedFields.addAll(Arrays.asList(fieldNameArr));
    }

    /**
     * 指定 设值实体字段 集合 设置传人的实体字段名集合
     *
     * @param settedFields
     */
    public void setupSettedFields(List<String> settedFields) {
        this.settedFields = settedFields;
    }

    /**
     * 添加设值实体字段
     *
     * @param fieldName
     */
    protected void addSettedField(String fieldName) {
        if (!settedFields.contains(fieldName)) {
            settedFields.add(fieldName);
        }
    }

    /**
     * 所有设过值的实体字段
     *
     * @return
     */
    public List<String> obtainSettedFields() {
        return settedFields;
    }


    /**
     * 设置主键值
     *
     * @param id
     */
    public void setId(String id) {
        this.id = id;
        addSettedField("id");
    }

    /**
     * 获取主键值
     *
     * @return
     */
    @Column(name = "id")
    @Id
    @GeneratedValue(generator = "")
    public String getId() {
        return id;
    }

    /**
     * 获取创建时间
     * @return 创建时间
     */
    @Column(name = "create_time")
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * 设置创建时间
     * @param createTime 创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    /**
     * 获取创建时间
     * @return 创建时间
     */
    @Column(name = "create_time")
    public Long getCreateUserId() {
        return createUserId;
    }

    public void setCreateUserId(Long createUserId) {
        this.createUserId = createUserId;
    }
    /**
     * 获取创建时间
     * @return 创建时间
     */
    @Column(name = "update_time")
    public Date getUpdateTime() {
        return updateTime;
    }

    /**
     * 设置更新时间
     * @param updateTime
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    /**
     * 获取更新用户
     * @return 更新用户
     */
    @Column(name = "update_user_id")
    public Long getUpdateUserId() {
        return updateUserId;
    }

    /**
     * 设置更新用户
     * @return 更新用户
     */
    public void setUpdateUserId(Long updateUserId) {
        this.updateUserId = updateUserId;
    }

    /**
     * 获取实体Mapper Class
     *
     * @return entity class
     */
    public Class<?> obtainEntityMapperClass() {
        throw new RuntimeException(this.getClass().getName() + " not implement the obtainEntityMapperClass method!");
    }

    /**
     * 设置属性值
     * @param field
     * @param value
     */
    public void setAttributeValue(String field, Object value) {
        if (field != null && field.length() < 1){
            throw new RuntimeException("field name is must.");
        }
        EntityUtil.setFieldValueByFieldName(this, field, value);
    }

    @Transient
    public Object getAttributeValue(String field) {
        if (field != null && field.length() < 1) {
            return null;
        }
        Object value = null;
        try {
            value = EntityUtil.getFieldValueByFieldName(this, field);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return value;
    }
}
